<template>
  <a-card :bordered="false">
    <!-- 操作按钮区域 -->
    <div class="table-operator">
      <form class="search-bar" @submit.prevent="handleSearch">
        <!-- <a-input-search
          v-model="keyword"
          placeholder="请输入关键字"
          style="width: 320px"
          enter-button
          @search="handleSearch"
        />
        <a-button type="primary" html-type="submit" style="margin-left: 8px;margin-right:8px">
          搜索
        </a-button> -->
        <a-button @click="handleAdd(1)" type="primary" icon="plus">新增测试项</a-button>
        <a-button @click="handleAdd(2)" type="primary" icon="plus">新增测试用例</a-button>
        <!-- Git操作按钮 -->
        <a-button @click="handleGitPush" type="primary" icon="vertical-align-top" :loading="pushLoading">推送</a-button>
        <a-button @click="handleGitPull" type="primary" icon="vertical-align-bottom" :loading="pullLoading"
          >拉取</a-button
        >
      </form>
    </div>

    <!-- Git操作状态显示 -->
    <a-alert
      v-if="gitOperationMessage"
      :message="gitOperationMessage"
      :type="gitOperationType"
      show-icon
      style="margin-bottom: 12px"
      closable
      @close="gitOperationMessage = ''"
    />

    <!-- table区域-begin -->
    <a-row class="bottom-box" type="flex">
      <!-- 左侧面板 -->
      <a-col class="left-pane">
        <!-- 模板库树结构 -->
        <a-card title="模板库" size="small" class="left-card" :body-style="{ padding: '12px', overflow: 'scroll' }">
          <!-- 右键菜单 -->
          <a-menu
            v-show="menuVisible"
            :style="{ position: 'fixed', zIndex: 9999, ...menuStyle }"
            @click="handleMenuClick"
          >
            <a-menu-item key="edit">编辑</a-menu-item>
            <a-menu-item key="delete">删除</a-menu-item>
          </a-menu>

          <a-directory-tree
            :tree-data="treeData"
            :replace-fields="replaceFields"
            @select="onTreeSelect"
            @rightClick="onRightClick"
            default-expand-all
          />
        </a-card>

        <!-- Git暂存区 -->
        <a-card
          :title="stagingCollapsed ? '暂存提交' : '暂存提交'"
          size="small"
          class="left-card git-card"
          :body-style="{ padding: stagingCollapsed ? '8px 12px' : '12px', height: stagingCollapsed ? 'auto' : '200px' }"
        >
          <template slot="extra">
            <a-button v-if="!stagingCollapsed" type="link" size="small" @click="handleGitStatus" title="刷新状态">
              <a-icon type="reload" />
            </a-button>
            <a-button type="link" size="small" @click="stagingCollapsed = !stagingCollapsed">
              <a-icon :type="stagingCollapsed ? 'down' : 'up'" />
            </a-button>
          </template>

          <div v-if="!stagingCollapsed" class="git-staging-container">
            <!-- 未暂存的文件 -->
            <div v-if="gitStatus.modified.length > 0 || gitStatus.untracked.length > 0" class="changes-section">
              <div class="section-title">未暂存的更改</div>
              <div class="file-list">
                <div v-for="file in gitStatus.modified" :key="file" class="file-item modified" @click="stageFile(file)">
                  <a-icon type="edit" />
                  <span class="file-name">{{ getFileName(file) }}</span>
                  <a-icon type="plus" class="stage-icon" title="添加到暂存区" />
                </div>
                <div
                  v-for="file in gitStatus.untracked"
                  :key="file"
                  class="file-item untracked"
                  @click="stageFile(file)"
                >
                  <a-icon type="file-add" />
                  <span class="file-name">{{ getFileName(file) }}</span>
                  <a-icon type="plus" class="stage-icon" title="添加到暂存区" />
                </div>
              </div>
            </div>

            <!-- 已暂存的文件 -->
            <div v-if="gitStatus.staged.length > 0" class="changes-section">
              <div class="section-title">已暂存的更改</div>
              <div class="file-list">
                <div v-for="file in gitStatus.staged" :key="file" class="file-item staged">
                  <a-icon type="check" />
                  <span class="file-name">{{ getFileName(file) }}</span>
                  <a-icon type="minus" class="unstage-icon" title="从暂存区移除" @click="unstageFile(file)" />
                </div>
              </div>
            </div>

            <!-- 提交区域 -->
            <div class="commit-section">
              <a-textarea
                v-model="commitMessage"
                placeholder="输入提交信息"
                :rows="1"
                style="margin-bottom: 8px;"
                size="small"
              />
              <a-button
                type="primary"
                size="small"
                :disabled="gitStatus.staged.length === 0 || !commitMessage.trim()"
                @click="handleGitCommit"
                :loading="commitLoading"
                block
              >
                提交更改
              </a-button>
            </div>

            <a-empty
              v-if="
                gitStatus.modified.length === 0 && gitStatus.untracked.length === 0 && gitStatus.staged.length === 0
              "
              description="工作区干净"
              :image-style="{ height: '40px' }"
            />
          </div>
          <div v-else class="collapsed-placeholder">
            <!-- 完全折叠时只显示标题文字，不需要额外内容 -->
          </div>
        </a-card>

        <!-- Git历史记录 -->
        <a-card
          :title="historyCollapsed ? '历史记录' : '历史记录'"
          size="small"
          class="left-card git-card"
          :body-style="{ padding: historyCollapsed ? '8px 12px' : '12px', height: historyCollapsed ? 'auto' : '200px' }"
        >
          <template slot="extra">
            <a-button v-if="!historyCollapsed" type="link" size="small" @click="refreshGitHistory" title="刷新历史">
              <a-icon type="reload" />
            </a-button>
            <a-button type="link" size="small" @click="historyCollapsed = !historyCollapsed">
              <a-icon :type="historyCollapsed ? 'down' : 'up'" />
            </a-button>
          </template>

          <div v-if="!historyCollapsed" class="git-history-container">
            <a-list v-if="gitHistory.length > 0" :data-source="gitHistory" size="small" class="git-list">
              <a-list-item slot="renderItem" slot-scope="item" class="git-list-item">
                <a-list-item-meta
                  :title="item.message"
                  :description="`${item.author} • ${formatDate(item.date)} • ${item.hash.substring(0, 7)}`"
                />
              </a-list-item>
            </a-list>
            <a-empty v-else description="暂无提交记录" :image-style="{ height: '40px' }" />
          </div>
          <div v-else class="collapsed-placeholder">
            <!-- 完全折叠时只显示标题文字，不需要额外内容 -->
          </div>
        </a-card>
      </a-col>

      <!-- 右侧中心区域 -->
      <a-col class="right-pane">
        <!-- 顶部：当前节点信息 -->
        <a-card size="small" style="margin-bottom:12px" v-if="showNodeInfo">
          <a-descriptions :column="2" bordered>
            <a-descriptions-item label="名称">
              {{ activeNode.caseName || '—' }}
            </a-descriptions-item>
            <a-descriptions-item label="简述">
              {{ activeNode.caseVersion || '—' }}
            </a-descriptions-item>
            <a-descriptions-item label="项目类型">
              {{ purposeText || '—' }}
            </a-descriptions-item>
            <a-descriptions-item label="ID">
              {{ activeNode.id || '—' }}
            </a-descriptions-item>
          </a-descriptions>
        </a-card>

        <!-- 搜索结果显示 -->
        <a-card v-if="isSearchMode" title="搜索结果" size="small">
          <div slot="extra">
            <a-button type="link" @click="clearSearch">返回树视图</a-button>
          </div>
          <a-list v-if="searchResults.length" :data-source="searchResults" item-layout="horizontal">
            <a-list-item slot="renderItem" slot-scope="item" @click="handleItemClick(item)">
              <a-list-item-meta
                :title="item.caseName"
                :description="`简述：${item.caseVersion || '—'} | 项目类型：${getPurposeText(item.purpose) || '—'}`"
              />
              <div slot="actions">
                <a-button type="link" @click.stop="handleEdit(item)">编辑</a-button>
                <a-button type="link" @click.stop="handleViewFiles(item)" v-if="item.purpose === 2">查看文件</a-button>
              </div>
            </a-list-item>
          </a-list>
          <a-empty v-else description="暂无匹配结果" />
        </a-card>

        <!-- 树节点内容显示 -->
        <div v-else>
          <!-- 文件模式 -->
          <a-card v-if="showFile" title="模板文件" size="small">
            <a-descriptions :column="1" bordered>
              <a-descriptions-item label="Python 文件">
                <div class="file-link-container">
                  <a-button type="link" @click="handleViewFile(activeNode.filePy, 'py')" :disabled="!activeNode.filePy">
                    {{ activeNode.filePy || '—' }}
                  </a-button>
                  <a-tag v-if="activeNode.filePy" color="blue">Python</a-tag>
                </div>
              </a-descriptions-item>
              <a-descriptions-item label="YAML 文件">
                <div class="file-link-container">
                  <a-button
                    type="link"
                    @click="handleViewFile(activeNode.fileYml, 'yml')"
                    :disabled="!activeNode.fileYml"
                  >
                    {{ activeNode.fileYml || '—' }}
                  </a-button>
                  <a-tag v-if="activeNode.fileYml" color="green">YAML</a-tag>
                </div>
              </a-descriptions-item>
            </a-descriptions>
          </a-card>

          <!-- 列表模式：显示当前节点及其所有下级节点 -->
          <a-card v-else :title="currentNodeTitle" size="small">
            <a-list v-if="nodeChildrenList.length" :data-source="nodeChildrenList" item-layout="horizontal">
              <a-list-item slot="renderItem" slot-scope="item" @click="handleItemClick(item)">
                <a-list-item-meta
                  :title="item.caseName"
                  :description="`简述：${item.caseVersion || '—'} | 项目类型：${getPurposeText(item.purpose) || '—'}`"
                />
                <div slot="actions">
                  <a-button type="link" @click.stop="handleEdit(item)">编辑</a-button>
                  <a-button type="link" @click.stop="handleViewFiles(item)" v-if="item.purpose === 2"
                    >查看文件</a-button
                  >
                </div>
              </a-list-item>
            </a-list>
            <a-empty v-else description="该节点下暂无数据" />
          </a-card>
        </div>
      </a-col>
    </a-row>
    <!-- 文件编辑弹窗 -->
    <a-modal
      title="文件编辑器"
      :visible="fileEditorVisible"
      width="80%"
      :confirm-loading="fileSaving"
      :maskClosable="false"
      @ok="handleSaveFile"
      @cancel="handleCloseEditor"
      :bodyStyle="{ padding: '0' }"
    >
      <div class="file-editor-container">
        <!-- 文件信息头部 -->
        <div class="file-header">
          <a-alert
            :message="`当前编辑: ${currentFile ? currentFile.name : ''}`"
            type="info"
            show-icon
            style="margin-bottom: 0; border-radius: 0;"
          />
        </div>

        <!-- 编辑器区域 -->
        <div class="editor-area">
          <a-spin :spinning="fileLoading">
            <div v-if="!fileLoading" class="editor-content">
              <!-- YAML文件使用代码编辑器 -->
              <div v-if="currentFile && currentFile.type === 'yml'" class="code-editor">
                <a-textarea
                  v-model="fileContent"
                  :rows="20"
                  placeholder="文件内容..."
                  style="width: 100%; font-family: 'Courier New', monospace;"
                />
              </div>

              <!-- Python文件使用代码编辑器 -->
              <div v-else-if="currentFile && currentFile.type === 'py'" class="code-editor">
                <a-textarea
                  v-model="fileContent"
                  :rows="20"
                  placeholder="文件内容..."
                  style="width: 100%; font-family: 'Courier New', monospace;"
                />
              </div>

              <!-- 其他文件类型 -->
              <div v-else class="text-editor">
                <a-textarea v-model="fileContent" :rows="20" placeholder="文件内容..." style="width: 100%" />
              </div>
            </div>

            <div v-else class="loading-state">
              <a-spin size="large" tip="加载文件中..." />
            </div>
          </a-spin>
        </div>
      </div>
    </a-modal>
    <test-user-case-modal ref="modalForm" @ok="modalFormOk"></test-user-case-modal>
  </a-card>
</template>

<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import TestUserCaseModal from './modules/TestUserCaseModal'
import { getAction, deleteAction } from '@/api/manage'

export default {
  name: 'TestUserCaseList',
  mixins: [JeecgListMixin, mixinDevice],
  components: {
    TestUserCaseModal
  },
  data() {
    return {
      description: '测试用例表管理页面',
      keyword: '',
      selectedKey: null,
      activeNode: {}, // 当前选中的节点
      replaceFields: { children: 'children', title: 'caseName', key: 'id' },
      treeData: [],
      url: {
        list: '/testUserCase/queryAllCase',
        delete: '/testUserCase/delete',
        deleteBatch: '/testUserCase/deleteBatch',
        exportXlsUrl: '/testUserCase/exportXls',
        importExcelUrl: '/testUserCase/importExcel',
        getList: '/testUserCase/queryAllCase',
        // Git相关接口
        gitPull: '/git/pull',
        gitPush: '/git/push',
        gitStatus: '/git/status',
        gitCommit: '/git/commit',
        gitHistory: '/git/history',
        gitStage: '/git/stage',
        gitUnstage: '/git/unstage'
      },
      dictOptions: {},
      superFieldList: [],
      menuVisible: false,
      menuStyle: { left: 0, top: 0 },
      rightNode: null, // 当前右键节点
      isSearchMode: false, // 是否处于搜索模式
      searchResults: [], // 搜索结果
      purposeMap: {
        0: '目录',
        1: '测试用例',
        2: '测试用例模板'
      },
      // Git相关数据
      pushLoading: false,
      pullLoading: false,
      commitLoading: false,
      gitOperationMessage: '',
      gitOperationType: 'info',
      gitHistory: [],
      gitStatus: {
        modified: [],
        untracked: [],
        staged: []
      },
      commitMessage: '',
      // 折叠状态 - 默认展开
      stagingCollapsed: false,
      historyCollapsed: false,
      fileEditorVisible: false,
      currentFile: null,
      fileContent: '',
      fileLoading: false,
      fileSaving: false,
      editorKey: 0 // 用于强制重新渲染编辑器
    }
  },
  created() {
    this.loadData()
    // this.loadGitData()
  },
  computed: {
    /* 是否显示节点信息 */
    showNodeInfo() {
      return this.activeNode && this.activeNode.id && !this.isSearchMode
    },
    /* 当前节点是否展示文件 */
    showFile() {
      return this.activeNode && this.activeNode.purpose === 2 && !this.isSearchMode
    },
    importExcelUrl: function() {
      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
    },
    /* 项目类型文本 */
    purposeText() {
      return this.getPurposeText(this.activeNode.purpose)
    },
    /* 当前节点标题 */
    currentNodeTitle() {
      if (this.activeNode.caseName) {
        return `节点内容: ${this.activeNode.caseName}`
      }
      return '节点内容'
    },
    /* 当前节点及其所有下级节点列表 */
    nodeChildrenList() {
      if (!this.selectedKey || !this.activeNode.id) return []

      // 获取当前节点及其所有下级节点
      const allChildren = this.getAllChildrenNodes(this.activeNode)
      return allChildren.filter(node => node.purpose !== 0) // 过滤掉目录类型的节点
    }
  },
  methods: {
    /* 查看和编辑文件 */
    async handleViewFile(filePath, fileType) {
      if (!filePath) {
        this.$message.warning('文件路径为空')
        return
      }

      try {
        this.fileLoading = true
        this.currentFile = {
          path: filePath,
          type: fileType,
          name: this.getFileName(filePath)
        }

        // 调用接口获取文件内容
        const res = await getAction('/sys/common/getFileContent', {
          filePath: filePath
        })

        if (res.success) {
          this.fileContent = res.result || ''
          this.fileEditorVisible = true
          this.editorKey += 1 // 强制重新渲染编辑器
        } else {
          this.$message.error('获取文件内容失败: ' + (res.message || '未知错误'))
        }
      } catch (error) {
        console.error('获取文件内容失败:', error)
        this.$message.error('获取文件内容失败: ' + error.message)
      } finally {
        this.fileLoading = false
      }
    },

    /* 保存文件 */
    async handleSaveFile() {
      if (!this.currentFile || !this.fileContent) {
        this.$message.warning('文件内容为空')
        return
      }

      try {
        this.fileSaving = true

        const params = {
          filePath: this.currentFile.path,
          content: this.fileContent
        }

        // 调用保存接口
        const res = await this.$http.post('/sys/common/saveFileContent', params)

        if (res.success) {
          this.$message.success('文件保存成功')
          this.fileEditorVisible = false
          this.currentFile = null
          this.fileContent = ''
        } else {
          this.$message.error('文件保存失败: ' + (res.message || '未知错误'))
        }
      } catch (error) {
        console.error('保存文件失败:', error)
        this.$message.error('保存文件失败: ' + error.message)
      } finally {
        this.fileSaving = false
      }
    },

    /* 关闭编辑器 */
    handleCloseEditor() {
      if (this.fileContent && this.hasUnsavedChanges()) {
        this.$confirm({
          title: '确认关闭',
          content: '文件内容已修改，确定要关闭吗？',
          onOk: () => {
            this.fileEditorVisible = false
            this.currentFile = null
            this.fileContent = ''
          }
        })
      } else {
        this.fileEditorVisible = false
        this.currentFile = null
        this.fileContent = ''
      }
    },

    /* 检查是否有未保存的更改 */
    hasUnsavedChanges() {
      // 这里可以添加更复杂的逻辑来检测文件是否被修改
      // 目前简单返回 true 表示总是提示
      return true
    },

    /* 获取文件名 */
    getFileName(filePath) {
      return filePath.split('/').pop() || filePath
    },
    handleAdd: function(type) {
      this.$refs.modalForm.add(type)
      this.$refs.modalForm.title = '新增'
      this.$refs.modalForm.disableSubmit = false
    },
    loadData() {
      getAction(this.url.list, {}).then(res => {
        if (res.success) {
          this.treeData = res.result
          console.log(res, 'res')
        } else {
          console.error('getDictItems error: : ', res)
          this.dictOptions = []
        }
      })
    },

    /* Git相关方法 */
    loadGitData() {
      this.refreshGitHistory()
      this.handleGitStatus()
    },

    // 刷新Git历史记录
    refreshGitHistory() {
      getAction(this.url.gitHistory)
        .then(res => {
          if (res.success) {
            this.gitHistory = res.result
          } else {
            this.showGitMessage('获取历史记录失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          console.error('获取Git历史记录失败:', error)
          this.showGitMessage('获取历史记录失败', 'error')
        })
    },

    // 检查Git状态
    handleGitStatus() {
      getAction(this.url.gitStatus)
        .then(res => {
          if (res.success) {
            this.gitStatus = res.result
          } else {
            this.showGitMessage('检查状态失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          console.error('检查Git状态失败:', error)
          this.showGitMessage('检查状态失败', 'error')
        })
    },

    // Git拉取
    handleGitPull() {
      this.pullLoading = true
      getAction(this.url.gitPull)
        .then(res => {
          this.pullLoading = false
          if (res.success) {
            this.showGitMessage('拉取成功', 'success')
            this.refreshGitHistory()
            this.handleGitStatus()
          } else {
            this.showGitMessage('拉取失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          this.pullLoading = false
          console.error('Git拉取失败:', error)
          this.showGitMessage('拉取失败', 'error')
        })
    },

    // Git推送
    handleGitPush() {
      this.pushLoading = true
      getAction(this.url.gitPush)
        .then(res => {
          this.pushLoading = false
          if (res.success) {
            this.showGitMessage('推送成功', 'success')
          } else {
            this.showGitMessage('推送失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          this.pushLoading = false
          console.error('Git推送失败:', error)
          this.showGitMessage('推送失败', 'error')
        })
    },

    // Git提交
    handleGitCommit() {
      if (!this.commitMessage.trim()) {
        this.showGitMessage('请输入提交信息', 'warning')
        return
      }

      this.commitLoading = true
      const params = {
        message: this.commitMessage
      }

      getAction(this.url.gitCommit, params)
        .then(res => {
          this.commitLoading = false
          if (res.success) {
            this.showGitMessage('提交成功', 'success')
            this.commitMessage = ''
            this.refreshGitHistory()
            this.handleGitStatus()
          } else {
            this.showGitMessage('提交失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          this.commitLoading = false
          console.error('Git提交失败:', error)
          this.showGitMessage('提交失败', 'error')
        })
    },

    // 添加到暂存区
    stageFile(filePath) {
      const params = { file: filePath }
      getAction(this.url.gitStage, params)
        .then(res => {
          if (res.success) {
            this.handleGitStatus()
          } else {
            this.showGitMessage('暂存文件失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          console.error('暂存文件失败:', error)
          this.showGitMessage('暂存文件失败', 'error')
        })
    },

    // 从暂存区移除
    unstageFile(filePath) {
      const params = { file: filePath }
      getAction(this.url.gitUnstage, params)
        .then(res => {
          if (res.success) {
            this.handleGitStatus()
          } else {
            this.showGitMessage('取消暂存失败: ' + res.message, 'error')
          }
        })
        .catch(error => {
          console.error('取消暂存失败:', error)
          this.showGitMessage('取消暂存失败', 'error')
        })
    },

    // 显示Git操作消息
    showGitMessage(message, type = 'info') {
      this.gitOperationMessage = message
      this.gitOperationType = type
      // 5秒后自动清除成功/信息类消息
      if (type === 'success' || type === 'info') {
        setTimeout(() => {
          this.gitOperationMessage = ''
        }, 5000)
      }
    },

    // 获取文件名（从路径中提取）
    getFileName(filePath) {
      return filePath.split('/').pop() || filePath
    },

    // 格式化日期
    formatDate(dateString) {
      if (!dateString) return ''
      const date = new Date(dateString)
      return `${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date
        .getMinutes()
        .toString()
        .padStart(2, '0')}`
    },

    /* 搜索触发 */
    handleSearch() {
      if (!this.keyword.trim()) {
        this.isSearchMode = false
        this.searchResults = []
        return
      }

      this.isSearchMode = true
      const kw = this.keyword.toLowerCase().trim()
      const allNodes = this.flattenAllNodes(this.treeData)

      // 搜索条件：匹配用例名称或版本
      this.searchResults = allNodes.filter(
        node =>
          (node.purpose !== 0 && // 排除目录节点
            node.caseName &&
            node.caseName.toLowerCase().includes(kw)) ||
          (node.caseVersion && node.caseVersion.toLowerCase().includes(kw))
      )

      // 清空当前选中的节点
      this.selectedKey = null
      this.activeNode = {}
    },
    /* 清空搜索 */
    clearSearch() {
      this.keyword = ''
      this.isSearchMode = false
      this.searchResults = []
    },
    /* 树选择 */
    onTreeSelect(keys) {
      if (keys.length === 0) return

      this.clearSearch()
      const node = this.findNode(this.treeData, keys[0])
      this.activeNode = node || {}
      this.selectedKey = keys[0] || null
    },
    /* 点击列表项 */
    handleItemClick(item) {
      this.activeNode = item
      // 如果点击的是树节点，可以高亮对应的树节点
      if (item.id) {
        this.selectedKey = item.id
      }
    },
    /* 查看文件 */
    handleViewFiles(item) {
      this.activeNode = item
      this.selectedKey = item.id
    },
    /* 工具：拍平所有节点（包括目录） */
    flattenAllNodes(nodes) {
      let res = []
      nodes.forEach(n => {
        res.push(n)
        if (n.children && n.children.length) {
          res = res.concat(this.flattenAllNodes(n.children))
        }
      })
      return res
    },
    /* 工具：获取节点及其所有下级节点 */
    getAllChildrenNodes(node) {
      let nodes = [node] // 包含当前节点本身

      if (node.children && node.children.length) {
        node.children.forEach(child => {
          nodes = nodes.concat(this.getAllChildrenNodes(child))
        })
      }

      return nodes
    },
    /* 工具：根据 key 查找任意节点 */
    findNode(nodes, key) {
      for (const n of nodes) {
        if (n.id == key) return n
        if (n.children) {
          const found = this.findNode(n.children, key)
          if (found) return found
        }
      }
      return null
    },
    /* 获取项目类型文本 */
    getPurposeText(purpose) {
      return this.purposeMap[purpose] || '—'
    },
    initDictConfig() {},
    getSuperFieldList() {
      let fieldList = []
      fieldList.push({ type: 'string', value: 'caseName', text: '用例名称', dictCode: '' })
      fieldList.push({ type: 'string', value: 'caseVersion', text: '用例版本', dictCode: '' })
      fieldList.push({ type: 'string', value: 'purpose', text: '测试目的', dictCode: '' })
      this.superFieldList = fieldList
    },
    /* ================= 右键 ================= */
    onRightClick(e) {
      const { event, node } = e
      // 根节点(pid===0)不弹菜单
      console.log(node.dataRef, 'node.dataRef')
      if (node.dataRef.pid == 0) return
      event.preventDefault()
      this.rightNode = node.dataRef
      this.menuStyle = { left: `${event.clientX}px`, top: `${event.clientY}px` }
      this.menuVisible = true
      // 点页面任意处关闭
      const close = () => {
        this.menuVisible = false
        document.removeEventListener('click', close)
      }
      this.$nextTick(() => document.addEventListener('click', close))
    },

    handleMenuClick({ key }) {
      if (key === 'delete') this.deleteNode(this.rightNode)
      if (key === 'edit') this.editNode(this.rightNode)
      this.menuVisible = false
    },

    /* ================= 删除 ================= */
    deleteNode(target) {
      let that = this
      deleteAction(that.url.delete, { id: target.id }).then(res => {
        if (res.success) {
          that.$message.success(res.message)
          this.refreshDisplay()
        } else {
          that.$message.warning(res.message)
        }
      })
    },

    editNode(target) {
      this.handleEdit(target)
    },

    refreshDisplay() {
      this.loadData()
      this.keyword = this.keyword.trim()
    }
  }
}
</script>
<style scoped>
@import '~@assets/less/common.less';
.right-pane .ant-descriptions-item-label {
  width: 80px;
  text-align: right;
}
/* 下部分：左右分栏，占剩余高度 */
.bottom-box {
  flex: 1;
  overflow: hidden;
  height: calc(100vh - 140px);
}

/* 左侧面板：固定宽度 */
.left-pane {
  width: 320px;
  border-right: 1px solid #eee;
  overflow-y: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 右侧中心区域：自适应 */
.right-pane {
  flex: 1;
  overflow-y: auto;
  padding: 12px 24px;
}

.ant-menu {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* 列表项悬停效果 */
.ant-list-item {
  cursor: pointer;
  transition: background-color 0.3s;
}
.ant-list-item:hover {
  background-color: #f5f5f5;
}

/* 左侧卡片样式 */
.left-card {
  margin-bottom: 0;
}

.left-card:first-child {
  flex: 1;
  min-height: 200px;
}

.left-card.git-card {
  min-height: auto;
  max-height: none;
}

/* 折叠状态下的卡片样式 */
.left-card.git-card .ant-card-body {
  transition: all 0.3s ease;
}

/* Git相关样式 */
.git-staging-container,
.git-history-container {
  height: 100%;
  max-height: 160px;
  overflow-y: auto;
}

.git-list {
  max-height: 120px;
  overflow-y: auto;
}

.git-list-item {
  padding: 6px 0;
  border-bottom: 1px solid #f0f0f0;
}

.git-list-item:last-child {
  border-bottom: none;
}

.changes-section {
  margin-bottom: 10px;
}

.section-title {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
  font-weight: 500;
}

.file-list {
  margin-bottom: 6px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 3px 6px;
  border-radius: 3px;
  margin-bottom: 2px;
  cursor: pointer;
  transition: background-color 0.2s;
  font-size: 12px;
}

.file-item:hover {
  background-color: #f5f5f5;
}

.file-item.modified {
  color: #1890ff;
}

.file-item.untracked {
  color: #52c41a;
}

.file-item.staged {
  color: #722ed1;
  background-color: #f9f0ff;
}

.file-name {
  flex: 1;
  margin: 0 6px;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stage-icon,
.unstage-icon {
  color: #999;
  cursor: pointer;
  font-size: 11px;
}

.stage-icon:hover {
  color: #52c41a;
}

.unstage-icon:hover {
  color: #ff4d4f;
}

.commit-section {
  border-top: 1px solid #f0f0f0;
  padding-top: 8px;
  margin-top: 8px;
}

.collapsed-placeholder {
  /* 完全折叠时不显示任何内容，只保留标题 */
  display: none;
}

/* 树样式调整 */
.ant-tree {
  font-size: 12px;
}

.ant-tree .ant-tree-node-content-wrapper {
  padding: 2px 4px;
}

.ant-tree .ant-tree-treenode {
  padding: 2px 0;
}

/* 折叠按钮样式 */
.ant-card-extra .ant-btn-link {
  padding: 0 4px;
  height: 20px;
}

.ant-card-extra .anticon {
  font-size: 12px;
}
</style>
